#define _CRT_SECURE_NO_WARNINGS 1

// 编译和链接
// 
// 翻译环境和运行环境
// 翻译环境：预编译 + 编译 + 汇编 + 链接

// 在ANSI C的任何一种实现中，存在两个不同的环境
// 第1种是翻译环境，在这个环境中源代码被转换为可执行的机器指令(二进制指令)
// 第2中是执行环境，它用于实际执行代码

// 翻译环境
// 在这个环境中源代码被转换成可执行的机器指令（二进制指令）

//#include <stdio.h>
//
//int main()
//{
//	printf("hehe\n");
//
//	return 0;
//}

// 翻译环境是怎么将源代码转换为可执行的机器指令？
// 翻译环境是由编译和链接两个大的过程组成的，而编译又可以分成：预处理（预编译）、编译、汇编

// 编译：几个.c文件经过编译器.exe成几个.obj文件（Linux下为.o），已经是二进制了
// 链接：几个.obj加上链接库（头文件等），经过链接器link.exe，成了可执行程序

// 预编译的阶段就有头文件的包含
// C语言中#开头的指令是预处理指令

// 预编译时候，会添加行号和文件名标识，方便后续编译器生成调试信息等

// 编译过程的本质上就是将C语言代码翻译成汇编代码
// 并且进行一系列的：词法分析、语法分析、语义分析及优化

// 词法分析：将源代码程序输入扫描器，扫描器的任务就是简单的进行词法分析
//			将代码中的字符分割成一系列的记号（关键字、标识符、字面量、特殊字符）

// 语法分析：将对扫描产生的记号进行语法分析，从而产生语法树

// 语义分析：由语义分析器来完成语义分析，即对表达式的语法层面分析
//			编译器所能做的分析是语义的静态分析。这包括声明和类型的匹配，类型的转换。
//			这个阶段会报告错误的语法分析

// 接下来就是汇编操作
// 汇编器是将汇编代码转变成机器可执行的指令  
// 每一个汇编语句几乎都对应一条机器指令，即根据汇编指令和机器指令的对照表一一翻译
// 也不做指令优化    

// 链接是一个复杂的过程，链接的时候需要把一堆文件链接在一起才生成可执行程序
// 链接过程主要包括：地址和空间分配，符号决议(判断选择哪一个)和重定位等这些步骤
// 链接解决的是一个项目中多文件、多模块之间互相调用的问题

// 声明外部符号
//#include <stdio.h>
//
//extern int Add(int x, int y);
//
//int main()
//{
//	int ret = Add(100, 200);
//	printf("%d\n", ret);
//
//	return 0;
//}
// 把多个目标文件链接生成一个可执行程序
// 符号的决议和重定位
// 对于更多实现细节，可以看《程序员的自我修养》来了解


// 已经生成可执行文件了，接下来就依赖运行环境
// 1.程序必须载入内存中。在有操作系统的环境中：一般这个由操作系统完成。
//   在独立的环境中，程序的载入必须由手工安排，也可能是通过可执行代码置入只读内存来完成

// 2.程序的执行便开始，接着便调用main函数

// 3.开始执行程序代码，这个时候程序将使用一个运行时堆栈（函数栈帧）
//   存储函数的局部变量和返回地址
//   程序同时也可以使用静态内存，存储于静态内存中的变量在程序的整个执行过程一直保留他们的值

// 4.终止程序 正常结束main函数，或者被迫意外终止


